﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Threading;
using System.IO;
using GW2LastOnline.Services;
using GW2LastOnline.Controls;

namespace GW2LastOnline
{
    public partial class formMain : Form
    {
        private struct RecordColumn
        {
            public const byte Name = 0;
            public const byte LastUpdated = 1;
            public const byte AchievementPoints = 2;
        }

        //private enum RecordColumn : byte { Name = 0, LastUpdated = 1, AchievementPoints = 2 };
        private enum FilterBy : short { None = -1, World = 0, Guild = 1, Friends = 2 };
        private enum FilterRegion : short { None = -1, EU = 0, NA = 1 };

        private List<DataGridViewRow> records;
        private DataGridViewColumn sortedColumn;
        private bool loginAsked;
        private bool closing;

        private Session session;
        private Achievements achievements;
        private Achievements.ListFilters[] achievementFilters;

        private formSearch expandedSearch;
        private int visibleRows;

        private string[] filterSearch;
        private string currentSearch;
        private string lastSearch;
        private bool delayingSearch;
        private DateTime lastSearchTime;

        private DateTime lastUpdated, nextUpdate;

        private FilterRegion selectedFilterRegion;
        private FilterBy selectedFilterBy;

        public formMain()
        {
            InitializeComponent();

            SetStyle(ControlStyles.ResizeRedraw, true);

            this.DoubleBuffered = true;
            this.BackColor = Color.White;

            Font fontGrid = gridRecords.DefaultCellStyle.Font;
            Fonts.Apply(Fonts.Cabin, this.comboFilter, this.comboFilterBy, this.comboRegion, this.gridRecords, this.labelFilterBy);
            gridRecords.DefaultCellStyle.Font = fontGrid;

            comboFilter.Visible = false;

            session = new Session();
            achievements = new Achievements(session);
            achievementFilters = new Achievements.ListFilters[2];
            records = new List<DataGridViewRow>();

            selectedFilterRegion = FilterRegion.None;
            selectedFilterBy = FilterBy.None;

            UpdateDisplaying();

            achievements.OnAchievementsPageUpdated += new Achievements.OnAchievementsPageUpdatedEventHandler(achievements_OnAchievementsPageUpdated);
            achievements.OnError += new Achievements.OnErrorEventHandler(achievements_OnError);

            new Thread(new ThreadStart(UpdateTimes)).Start();
        }

        void achievements_OnError(Achievements.LeaderboardException e)
        {
            if (e.Code == Achievements.LeaderboardException.ErrorCode.NotAuthorized)
            {
                try
                {
                    this.BeginInvoke(new MethodInvoker(delegate
                    {
                        progressLoading.Visible = false;

                        //session no longer valid, re-request
                        SelectFilterBy(GetSelectedFilterBy());
                    }));
                }
                catch { }
            }
            else if (e.Code == Achievements.LeaderboardException.ErrorCode.Timeout)
            {
                try
                {
                    this.BeginInvoke(new MethodInvoker(delegate
                        {
                            progressLoading.Visible = false;
                        }));
                }
                catch { }
            }
        }

        void achievements_OnAchievementsPageUpdated(Achievements.AchievementsPage page)
        {
            try
            {
                this.BeginInvoke(new MethodInvoker(delegate
                {
                    /*
                    if (!IsSelected((page.region == Achievements.Region.EU) ? FilterRegion.EU : FilterRegion.NA))
                        return;
                    */

                    if (IsLoginRequired(GetSelectedFilterBy()) && !page.loggedIn)
                    {
                        //the session ended while requesting a page, but to access the correct page, a valid login was required
                        //this problem is only valid when trying to load guild listings, since the listings are gathered from a page not requiring a login
                        //if left unchecked, the login won't be verified until the friends list is browsed, causing the list of guilds to appear blank until then
                        achievements.Abort();
                        session.Invalidate();
                        progressLoading.Visible = false;
                        SelectFilterBy(GetSelectedFilterBy());
                        return;
                    }

                    progressLoading.Visible = page.hasNext;
                    UpdateFilters(GetSelectedRegion(), page.filters);
                    SetLastUpdated(FixDate(page.updated.last), FixDate(page.updated.next));

                    if (page.records != null)
                    {
                        bool added = false;
                        foreach (Achievements.PlayerRecord record in page.records)
                            added = AddRow(record) || added;
                        if (added)
                            SortGrid();
                    }

                    UpdateDisplaying();
                }));
            }
            catch { }
        }

        private void UpdateFilters(FilterRegion region, Achievements.ListFilters filters)
        {
            int index = (int)region;
            Achievements.ListFilters f = achievementFilters[index];

            if (!IsEqual(filters.guilds, f.guilds))
            {
                achievementFilters[index].guilds = filters.guilds;
                if (IsSelected(FilterBy.Guild))
                    SelectList(filters.guilds);
            }
            if (!IsEqual(filters.worlds, f.worlds))
            {
                achievementFilters[index].worlds = filters.worlds;
                if (IsSelected(FilterBy.World))
                    SelectList(filters.worlds);
            }
        }

        private bool IsEqual(List<string> a, List<string> b)
        {
            if ((a == null || b == null) && (a != null || b != null))
                return false;
            else if (a == null && b == null)
                return true;
            else
            {
                if (a.Count != b.Count)
                    return false;

                return (a[0].Equals(b[0]));
            }
        }

        private Achievements.Region GetRegion(FilterRegion region)
        {
            return (region == FilterRegion.EU) ? Achievements.Region.EU : Achievements.Region.NA;
        }

        private FilterRegion GetSelectedRegion()
        {
            return selectedFilterRegion;
        }

        private FilterBy GetSelectedFilterBy()
        {
            return selectedFilterBy;
        }

        private bool IsSelected(FilterRegion region)
        {
            return GetSelectedRegion() == region;
        }

        private bool IsSelected(FilterBy filter)
        {
            return GetSelectedFilterBy() == filter;
        }

        private void UpdateTimes()
        {
            while (!closing)
            {
                DateTime d = DateTime.Now.AddMinutes(1);
                do
                {
                    Thread.Sleep(1000);
                }
                while (DateTime.Now < d && !closing);

                try
                {
                    this.Invoke(new MethodInvoker(delegate
                        {
                            RefreshLastUpdated();
                            gridRecords.Refresh();
                        }));
                }
                catch { }
            }
        }

        private DateTime FixDate(DateTime date)
        {
            //note that the NA leaderboards are off by +1 hours
            //the EU leaderboards were correct, but are now also off by an hour

            //if (IsSelected(FilterRegion.NA))
            return date.Subtract(new TimeSpan(1, 0, 0));
            //return date;
        }

        private string FormatRemaining(TimeSpan t)
        {
            int hours = (int)t.TotalHours;
            if (hours > 1)
                return hours + " hours";
            else if (hours == 1)
                return "an hour";
            else
            {
                int minutes = (int)t.TotalMinutes;
                if (minutes > 1)
                    return minutes + " minutes";
                else
                    return "a minute";
            }
        }

        private void SetLastUpdated(DateTime lastUpdated, DateTime nextUpdate)
        {
            if (lastUpdated == DateTime.MinValue && nextUpdate != DateTime.MinValue)
                return;

            if (this.lastUpdated != lastUpdated || this.nextUpdate != nextUpdate)
            {
                this.lastUpdated = lastUpdated;
                this.nextUpdate = nextUpdate;
            }

            RefreshLastUpdated();
        }

        private void RefreshLastUpdated()
        {
            if (lastUpdated != DateTime.MinValue)
            {
                string updated = "Leaderboards updated " + FormatRemaining(DateTime.Now.Subtract(lastUpdated)) + " ago";
                if (nextUpdate != DateTime.MinValue)
                {
                    if (DateTime.Now > nextUpdate)
                        updated += ", next update is available";
                    else
                        updated += ", next update in " + FormatRemaining(nextUpdate.Subtract(DateTime.Now));
                }
                labelUpdated.Text = updated;
                labelUpdated.Visible = true;
            }
            else
                labelUpdated.Visible = false;
        }

        private void DrawBackground(Graphics g, Rectangle clip, Image image, int x, int y)
        {
            Rectangle dest = new Rectangle();
            dest.X = x;
            dest.Y = y;
            dest.Width = image.Width;
            dest.Height = image.Height;
            dest = Rectangle.Intersect(clip, dest);

            if (dest != Rectangle.Empty)
                g.DrawImage(image, dest, dest.X - x, dest.Y - y, dest.Width, dest.Height, GraphicsUnit.Pixel);
        }

        private bool Login()
        {
            loginAsked = true;

            formLogin login = new formLogin();
            if (login.ShowDialog(this) == DialogResult.OK)
            {
                session.Cookies = login.Cookies;

                login.Dispose();
                return true;
            }

            login.Dispose();
            return false;
        }

        private bool AddRow(string name, int points, DateTime updated)
        {
            DataGridViewRow row = new DataGridViewRow();
            row.CreateCells(gridRecords);

            row.Cells[RecordColumn.Name].Value = name;
            row.Cells[RecordColumn.AchievementPoints].Value = points;
            row.Cells[RecordColumn.LastUpdated].Value = new LastUpdatedCellDisplay(updated);
            row.Cells[RecordColumn.LastUpdated].ToolTipText = updated.ToLongDateString() + " " + updated.ToLongTimeString();

            records.Add(row);

            if (MatchesFilter(row, filterSearch))
            {
                gridRecords.Rows.Add(row);
                row.Selected = false;
                visibleRows++;

                return true;
            }
            else
            {
                return false;
            }
        }

        private void UpdateDisplaying()
        {
            if (this.InvokeRequired)
            {
                try
                {
                    this.BeginInvoke(new MethodInvoker(UpdateDisplaying));
                }
                catch { }
                return;
            }

            if (filterSearch != null && visibleRows != records.Count)
                labelTotal.Text = "Displaying " + visibleRows + " of " + records.Count + " record" + ((records.Count == 1) ? "" : "s");
            else
                labelTotal.Text = "Displaying " + records.Count + " record" + ((records.Count == 1) ? "" : "s");
        }

        private bool AddRow(Achievements.PlayerRecord record)
        {
            return AddRow(record.name, record.points, FixDate(record.updated));
        }

        private void formMain_Load(object sender, EventArgs e)
        {
        }

        private void comboFilterBy_SelectedIndexChanged(object sender, EventArgs e)
        {
            achievements.Abort();
            comboFilter.Items.Clear();
            progressLoading.Visible = false;

            if (comboFilterBy.SelectedIndex != -1)
                SelectFilterBy((selectedFilterBy = (FilterBy)comboFilterBy.SelectedIndex));
        }

        private void comboRegion_SelectedIndexChanged(object sender, EventArgs e)
        {
            achievements.Abort();
            progressLoading.Visible = false;

            if (comboRegion.SelectedIndex != -1)
                SelectRegion((selectedFilterRegion = (FilterRegion)comboRegion.SelectedIndex));
        }

        private bool IsLoginRequired(FilterBy filter)
        {
            return (filter == FilterBy.Friends || filter == FilterBy.Guild);
        }

        private void SelectRegion(FilterRegion region)
        {
            comboFilter.Items.Clear();
            SelectFilterBy(GetSelectedFilterBy());
        }

        private void RequestLists()
        {
            progressLoading.Visible = true;
            achievements.RequestAchievementsPage(GetRegion(GetSelectedRegion()));
        }

        private void RequestWorld()
        {
            progressLoading.Visible = true;
            achievements.RequestWorld(GetRegion(GetSelectedRegion()), (string)comboFilter.SelectedItem);
        }

        private void RequestGuild()
        {
            progressLoading.Visible = true;
            achievements.RequestGuild(GetRegion(GetSelectedRegion()), (string)comboFilter.SelectedItem);
        }

        private void RequestFriends()
        {
            progressLoading.Visible = true;
            achievements.RequestFriends(GetRegion(GetSelectedRegion()));
        }

        private void ClearRecords()
        {
            gridRecords.Rows.Clear();
            records.Clear();
            visibleRows = 0;
            UpdateDisplaying();
        }

        private void comboFilter_VisibleChanged(object sender, EventArgs e)
        {
            int x;

            if (comboFilter.Visible)
                x = comboFilter.Location.X + comboFilter.Width + 16;
            else
                x = comboFilterBy.Location.X + comboFilterBy.Width + 16;

            progressLoading.Location = new Point(x, progressLoading.Location.Y);
        }

        private void SelectList(List<string> list)
        {
            string selected = (string)comboFilter.SelectedItem;
            comboFilter.Items.Clear();
            comboFilter.Visible = (list != null);

            if (list == null)
                return;

            int index = -1;
            foreach (string item in list)
            {
                comboFilter.Items.Add(item);
                if (item == selected)
                    index = comboFilter.Items.Count - 1;
            }

            if (index != -1)
                comboFilter.SelectedIndex = index;
        }

        private void SelectFilterBy(FilterBy filter)
        {
            if (IsSelected(FilterRegion.None))
                return;

            if (IsLoginRequired(filter) && !session.IsValid())
            {
                if (!Login()) //ask the user to login, if cancelled, abort
                {
                    SelectList(null);
                    return;
                }
            }
            else if (!loginAsked)
                Login();

            if (filter == FilterBy.Guild)
            {
                List<string> list = achievementFilters[(int)GetSelectedRegion()].guilds;
                if (list == null && session.IsValid())
                {
                    SelectList(null);
                    RequestLists();
                }
                else
                    SelectList(list);
            }
            else if (filter == FilterBy.Friends)
            {
                SelectList(null);
                ClearRecords();
                RequestFriends();
            }
            else if (filter == FilterBy.World)
            {
                List<string> list = achievementFilters[(int)GetSelectedRegion()].worlds;
                if (list == null)
                {
                    SelectList(null);
                    RequestLists();
                }
                else
                    SelectList(list);
            }
            else
            {
                //unknown filter by selected (nothing selected), select the first one
                comboFilterBy.SelectedIndex = 0;
            }
        }

        private void comboFilter_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (comboFilter.SelectedIndex != -1 && !IsSelected(FilterRegion.None))
            {
                ClearRecords();

                if (selectedFilterBy == FilterBy.Guild)
                    RequestGuild();
                else if (selectedFilterBy == FilterBy.Friends)
                    RequestFriends(); //note there's no filters currently available for friends, so this can never occur
                else if (selectedFilterBy == FilterBy.World)
                    RequestWorld();
            }
        }

        private void formMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            closing = true;
            achievements.Abort();
        }

        private void formMain_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            Rectangle dest = new Rectangle();
            int width = this.ClientSize.Width;

            Image left = Properties.Resources.backgroundLeft;
            Image right = Properties.Resources.backgroundRight;
            Image leftFade = Properties.Resources.backgroundLeftFade;
            Image rightFade = Properties.Resources.backgroundRightFade;

            dest.X = left.Width + leftFade.Width;
            dest.Y = 0;
            dest.Width = width - right.Width - rightFade.Width - dest.X;
            dest.Height = gridRecords.Location.Y;

            dest = Rectangle.Intersect(e.ClipRectangle, dest);
            if (dest != Rectangle.Empty)
                g.FillRectangle(new SolidBrush(Color.FromArgb(196, 22, 21)), dest);

            DrawBackground(e.Graphics, e.ClipRectangle, rightFade, width - right.Width - rightFade.Width - 5, 0);
            DrawBackground(e.Graphics, e.ClipRectangle, leftFade, left.Width + 5, 0);
            DrawBackground(e.Graphics, e.ClipRectangle, right, width - right.Width - 5, 0);
            DrawBackground(e.Graphics, e.ClipRectangle, left, 5, 0);
        }

        private void gridRecords_SortCompare(object sender, DataGridViewSortCompareEventArgs e)
        {
            if (e.Column.Index == RecordColumn.LastUpdated)
            {
                //sort by last updated, if equal, sort by name
                e.Handled = true;

                int i = ((LastUpdatedCellDisplay)e.CellValue1).Date.CompareTo(((LastUpdatedCellDisplay)e.CellValue2).Date);
                if (i == 0)
                    i = ((string)gridRecords.Rows[e.RowIndex1].Cells[RecordColumn.Name].Value).CompareTo((string)gridRecords.Rows[e.RowIndex2].Cells[RecordColumn.Name].Value);

                e.SortResult = i;
            }
        }

        private void gridRecords_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            DataGridViewColumn newColumn = gridRecords.Columns[e.ColumnIndex];
            DataGridViewColumn oldColumn = gridRecords.SortedColumn;

            if (e.Button == MouseButtons.Left && oldColumn != newColumn)
            {
                if (oldColumn != null)
                    oldColumn.HeaderCell.Style.BackColor = Color.Black;

                newColumn.HeaderCell.Style.BackColor = Color.FromArgb(47, 47, 47);
                newColumn.HeaderCell.Style.ApplyStyle(newColumn.HeaderCell.Style);
            }
        }

        private void gridRecords_Sorted(object sender, EventArgs e)
        {
            if (sortedColumn != gridRecords.SortedColumn)
            {
                if (sortedColumn != null)
                    sortedColumn.HeaderCell.Style.BackColor = Color.Black;
                gridRecords.SortedColumn.HeaderCell.Style.BackColor = Color.FromArgb(47, 47, 47);
                sortedColumn = gridRecords.SortedColumn;
            }
        }

        private bool MatchesFilter(DataGridViewRow row, string[] filters)
        {
            if (filters == null)
                return true;
            else
            {
                bool matches = false;

                string value = (string)row.Cells[RecordColumn.Name].Value;
                foreach (string filter in filters)
                {
                    if (value.IndexOf(filter, 0, StringComparison.InvariantCultureIgnoreCase) >= 0)
                    {
                        matches = true;
                        break;
                    }
                }

                return matches;
            }
        }

        private void ApplyFilter(string filter)
        {
            string[] search;

            if (filter.Length > 0)
            {
                search = filter.Split(',');
                if (search.Length > 1 && filter.IndexOf(", ") >= 0)
                    for (int i = 0; i < search.Length; i++)
                        search[i] = search[i].Trim();
            }
            else
                search = null;

            filterSearch = search;

            List<DataGridViewRow> matching;

            if (search == null)
            {
                if (gridRecords.Rows.Count == records.Count)
                    return;
                matching = records;
            }
            else
            {
                matching = new List<DataGridViewRow>();
                for (int i = 0; i < records.Count; i++)
                {
                    if (MatchesFilter(records[i], search))
                        matching.Add(records[i]);
                }
            }

            this.BeginInvoke(new MethodInvoker(delegate
            {
                Utils.SuspendDrawing(gridRecords);

                gridRecords.Rows.Clear();
                foreach (DataGridViewRow row in matching)
                {
                    gridRecords.Rows.Add(row);
                    row.Selected = false;
                }

                SortGrid();

                Utils.ResumeDrawing(gridRecords);

                visibleRows = matching.Count;
                UpdateDisplaying();
            }));
        }

        private void SortGrid()
        {
            if (sortedColumn != null)
                gridRecords.Sort(sortedColumn, (gridRecords.SortOrder == SortOrder.Ascending) ? ListSortDirection.Ascending : ListSortDirection.Descending);
        }

        private void OnSearchChanged(string search)
        {
            lastSearchTime = DateTime.Now;
            currentSearch = search;

            lock (this)
            {
                if (!delayingSearch)
                    delayingSearch = true;
                else
                    return;
            }

            new Thread(new ThreadStart(delegate
            {
                while (DateTime.Now.Subtract(lastSearchTime).TotalMilliseconds < 500)
                {
                    Thread.Sleep(100);
                }

                if (lastSearch != currentSearch)
                {
                    lastSearch = currentSearch;
                    ApplyFilter(currentSearch);
                }

                lock (this)
                {
                    delayingSearch = false;
                }
            })).Start();
        }

        private void buttonSearch_Click(object sender, EventArgs e)
        {
            if (expandedSearch != null)
            {
                expandedSearch.Focus();
                return;
            }

            ImageButton button = (ImageButton)sender;
            button.ImageFixed = Properties.Resources.buttonZoomSelected;

            SearchBox searchBox = new SearchBox();
            searchBox.Width = 140;
            if (currentSearch != null)
                searchBox.Text = currentSearch;

            searchBox.TextChanged += new EventHandler(delegate
            {
                OnSearchChanged(searchBox.Text);
            });

            searchBox.ExpandClicked += new EventHandler(delegate
            {
                expandedSearch = new formSearch(currentSearch);
                expandedSearch.Location = new Point(0, 0);

                expandedSearch.SetTextBoxScreenPosition(searchBox.Controls[0].PointToScreen(Point.Empty));

                expandedSearch.FormClosed += new FormClosedEventHandler(delegate
                {
                    OnSearchChanged(expandedSearch.Text);
                    if (expandedSearch.Text.Length == 0)
                        button.ImageFixed = null;
                    expandedSearch.Dispose();
                    expandedSearch = null;
                });
                expandedSearch.TextChanged += new EventHandler(delegate
                {
                    OnSearchChanged(expandedSearch.Text);
                });
                expandedSearch.Show(this);
            });

            ToolStripDropDown dropDown = new ToolStripDropDown();
            dropDown.BackColor = Color.White;

            dropDown.Closed += new ToolStripDropDownClosedEventHandler(delegate
            {
                if (expandedSearch == null)
                {
                    if (searchBox.Text.Length == 0)
                        button.ImageFixed = null;
                    OnSearchChanged(searchBox.Text);
                }
            });

            dropDown.Items.Add(new ToolStripControlHost(searchBox));

            Point p = this.PointToScreen(button.Location);
            p.Offset(button.Width / 2 + 10, button.Height / 2);
            dropDown.Show(p);
        }

        private void gridRecords_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {

        }

        private void buttonFile_Click(object sender, EventArgs e)
        {
            ImageButton button = (ImageButton)sender;

            Point p = this.PointToScreen(button.Location);
            p.Offset(button.Width / 2 + 10, button.Height / 2);

            loginToolStripMenuItem.Visible = !(logoutToolStripMenuItem.Visible = session.IsValid());

            contextFile.Show(p);
        }

        private void exportToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog dialog = new SaveFileDialog();
            dialog.Filter = "Text Document|*.txt|CSV|*.csv";
            dialog.Title = "Export records";

            if (dialog.ShowDialog() == DialogResult.OK)
            {
                StreamWriter stream = null;
                try
                {
                    stream = new StreamWriter(File.OpenWrite(dialog.FileName));

                    if (dialog.FilterIndex == 2)
                    {
                        stream.WriteLine("name,last updated,achievement points");
                    }

                    for (int i = 0; i < records.Count; i++)
                    {
                        DataGridViewRow row = records[i];

                        DateTime d = ((LastUpdatedCellDisplay)row.Cells[RecordColumn.LastUpdated].Value).Date;
                        if (dialog.FilterIndex == 1)
                        {
                            stream.WriteLine((string)row.Cells[RecordColumn.Name].Value);
                            stream.WriteLine("Achievements: " + (int)row.Cells[RecordColumn.AchievementPoints].Value);
                            stream.WriteLine("Last updated: " + d.ToShortDateString() + " " + d.ToLongTimeString());
                            stream.WriteLine();
                        }
                        else if (dialog.FilterIndex == 2)
                        {
                            stream.WriteLine((string)row.Cells[RecordColumn.Name].Value + "," + d.ToShortDateString() + " " + d.ToLongTimeString() + "," + (int)row.Cells[RecordColumn.AchievementPoints].Value);
                        }
                    }

                    stream.Flush();
                    stream.Close();
                    stream = null;
                }
                catch (Exception err)
                {
                    MessageBox.Show(err.Message, "An error has occured", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    if (stream != null)
                        stream.Close();
                }
            }
        }

        private class LastUpdatedCellDisplay
        {
            public LastUpdatedCellDisplay(DateTime date)
            {
                this.Date = date;
            }

            public DateTime Date
            {
                get;
                set;
            }

            public override string ToString()
            {
                TimeSpan t = DateTime.Now.Subtract(this.Date);
                int days = (int)t.TotalDays;

                if (days < 1)
                {
                    int hours = (int)t.TotalHours;
                    if (hours > 1)
                        return hours + " hours ago";
                    else if (hours == 1)
                        return "an hour ago";
                    else
                    {
                        int minutes = (int)t.TotalMinutes;
                        if (minutes > 1)
                            return minutes + " minutes ago";
                        else
                            return "a minute ago";
                    }
                }
                else if (days < 2)
                    return "Yesterday";
                else if (days < 30)
                    return (int)t.TotalDays + " days ago";
                else if (days < 365)
                {
                    int months = days / 30;
                    if (months == 1)
                        return "Last month";
                    else
                        return months + " months ago";
                }
                else
                {
                    int years = days / 365;
                    if (years == 1)
                        return "Last year";
                    else
                        return years + " years ago";
                }
            }
        }

        private void loginToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Login();
        }

        private void logoutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Account.Logout(session.Cookies);
            session.Invalidate();
        }
    }
}
